package com.haifeng.jupiter.auth.impl;

import cn.hutool.json.JSONUtil;
import com.haifeng.jupiter.auth.dto.PermissionDto;
import com.haifeng.jupiter.auth.dto.UserDto;
import com.haifeng.jupiter.auth.mapper.UserMapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;

/**
 * <p>
 *  自定义UserDetailsService
 * </p>
 *
 * @author: Haifeng
 * @date: 2020-08-11
 */
@Slf4j
@Service
@AllArgsConstructor
public class UserDetailsServiceImpl implements UserDetailsService {

    private final UserMapper userMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        //根据用户名查询出用户信息及权限信息，涉及到密码，直接查数据库
        UserDto userDto = userMapper.getUserByUsername(username);
        if (userDto == null) {
            log.info("[UserDetailsServiceImpl]用户名或者密码错误：用户{}不存在", username);
            throw new BadCredentialsException("用户名或者密码错误");
        }
        // 或者让实体实现UserDetailsService
        String password = userDto.getPassword();
        boolean enabled = userDto.getEnabled();
        boolean accountNonExpired = userDto.getAccountNonExpired();
        boolean credentialsNonExpired = userDto.getCredentialsNonExpired();
        boolean accountNonLocked = userDto.getAccountNonLocked();
        Collection<? extends GrantedAuthority> authorities = getAuthorities(userDto.getPermissionList());

        // 封装JWT需要包含的信息
        Map<String, Object> jwt = new HashMap<>(2);
        jwt.put("username", username);
        jwt.put("id", userDto.getId());
        jwt.put("superAdmin", userDto.getSuperAdmin());
        jwt.put("permissions", userDto.getPermissionList());
        String uname = JSONUtil.toJsonStr(jwt);
        return new org.springframework.security.core.userdetails.User(
                uname, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
    }

    /**
     * 业务描述：转换权限
     *
     * @param permissions
     * @return
     */
    public Collection<? extends GrantedAuthority> getAuthorities(Set<PermissionDto> permissions) {
        List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
        if (!CollectionUtils.isEmpty(permissions)) {
            permissions.forEach(permissionDto -> {
                if (permissionDto != null && permissionDto.getPermissionCode() != null) {
                    GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(permissionDto.getPermissionCode());
                    grantedAuthorities.add(grantedAuthority);
                }
            });
        }
        return grantedAuthorities;
    }
}
